home *** CD-ROM | disk | FTP | other *** search
/ Practical Algorithms for Image Analysis / Practical Algorithms for Image Analysis.iso / TARFILE.GZ / tarfile / ch_4.5 / xbdy / xbdy.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-11  |  6.7 KB  |  310 lines

  1. /* 
  2.  * xbdy.c
  3.  * 
  4.  * Practical Algorithms for Image Analysis
  5.  * 
  6.  * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
  7.  */
  8.  
  9. /*
  10.  * XBDY
  11.  *
  12.  * detection and encoding of planar boundaries in given image,
  13.  * implementing an algorithm by C. T. Zahn [1969]
  14.  *
  15.  */
  16. #include "xbdy.h"
  17.  
  18.  
  19. #define    WINDOW_ROWS    3
  20. #define NDIRECTIONS    8
  21.  
  22. #define    THRESH        1
  23. #define MIN_POLY_SIZE    20
  24. #define    ZERO        0
  25. #define ROOT2        1.414213562
  26.  
  27. #define    NA_MAX        128             /* lim of points, see ph.c */
  28.  
  29. #define    ON        1
  30. #define    OFF        0
  31.  
  32. #define    RESET        ON
  33. #define NO_RESET    OFF
  34.  
  35. #undef    DEBUG
  36. #undef    SHOW_CURV_PT
  37.  
  38.  
  39. /* global variables */
  40. extern short tiffInput;         /* flag=0 if no ImageIn to set tags; else =1 */
  41. struct curv_points *curv_head_in[NDIRECTIONS];
  42. struct curv_points *curv_head_out[NDIRECTIONS];
  43. struct curv_points *curv_tail_in[NDIRECTIONS];
  44. struct curv_points *curv_tail_out[NDIRECTIONS];
  45.  
  46. struct polygon *poly_head_ptr;
  47. struct polygon *poly_tail_ptr;
  48. float *delta_phik, *delta_lk;
  49.  
  50. long ncp = 0;
  51.  
  52. int loop_switch = ON;           /* enable/disable loop for polyg. approx */
  53. int hull_switch = ON;           /* enable/disable eval of convex hull */
  54. int n_ap_max = NA_MAX;          /* max no allowed vertices in approx. poly */
  55.  
  56. extern char *optarg;
  57. extern int optind, opterr;
  58. extern short tiffInput;         /* flag=0 if no ImageIn to set tags; else =1 */
  59.  
  60.  
  61. /*
  62.  * usage of routine
  63.  */
  64. void
  65. usage (char *progname)
  66. {
  67.   progname = last_bs (progname);
  68.   printf ("USAGE: %s inimg outimg [-L]\n", progname);
  69.   printf ("\n%s detects and encodes planar boundaries in a given image,\n", progname);
  70.   printf ("implementing an algorithm by C. T. Zahn [1969]\n\n");
  71.   printf ("ARGUMENTS:\n");
  72.   printf ("       inimg: input image filename (TIF)\n");
  73.   printf ("      outimg: output image filename (TIF)\n\n");
  74.   printf ("OPTIONS:\n");
  75.   printf ("          -L: print Software License for this module\n");
  76.  
  77.   exit (1);
  78. }
  79.  
  80. void
  81. init_structs ()
  82. {
  83.   int m;
  84.  
  85.   for (m = 0; m < NDIRECTIONS; m++) {
  86.     curv_tail_in[m] = curv_tail_out[m] = NULL;
  87.     curv_head_in[m] = curv_head_out[m] = NULL;
  88.   }
  89.   poly_head_ptr = NULL;
  90.   poly_tail_ptr = NULL;
  91. }
  92.  
  93. /*
  94.  * acquire first three rows from input image
  95.  * and transfer them to the window
  96.  */
  97. void
  98. xfer_first_3_rows (unsigned char *window[], Image * imgIO)
  99. {
  100.   int ir;
  101.  
  102.   for (ir = 0; ir < 3; ir++)
  103.     getrow (*(window + ir), ir, imgIO);
  104. }
  105.  
  106. /*
  107.  * acquire next from input image
  108.  * and transfer it to the window
  109.  */
  110. void
  111. xfer_next_row (unsigned char *window[], int ir, Image * imgIO)
  112. {
  113.   int y;
  114.   unsigned char *char_ptr;
  115.  
  116.   char_ptr = *(window + (ir % WINDOW_ROWS));
  117.   y = ir + 3;                   /* offset of 3 from first_3_rows */
  118.   getrow (char_ptr, y, imgIO);
  119. }
  120.  
  121. /*
  122.  * zero border error message
  123.  */
  124. void
  125. border_err (int row, int col)
  126. {
  127.   printf ("...AOI border not zeroed at row %d, col %d\n", row, col);
  128.   exit (1);
  129. }
  130.  
  131. /*
  132.  * image border must be zeroed -- check it!
  133.  */
  134. void
  135. check_border (unsigned char *window[], int ir, int jmax, int imax, Image * imgIO)
  136. {
  137.   int jc;
  138.   unsigned char *char_ptr;
  139.  
  140.   if (ir == 0) {
  141.     char_ptr = *(window + (ir % WINDOW_ROWS));
  142.     for (jc = 0; jc < jmax; jc++)
  143.       if (*(char_ptr + jc) != ZERO)
  144.         border_err (ir, jc);
  145.   }
  146.   if (ir == (imax - WINDOW_ROWS)) {
  147.     char_ptr = *(window + ((ir + 0) % WINDOW_ROWS));
  148.     if (*(char_ptr) != ZERO)
  149.       border_err (ir, 0);
  150.     if (*(char_ptr + (jmax - 1)) != ZERO)
  151.       border_err (ir, jmax - 1);
  152.  
  153.     char_ptr = *(window + ((ir + 1) % WINDOW_ROWS));
  154.     if (*(char_ptr) != ZERO)
  155.       border_err (ir + 1, 0);
  156.     if (*(char_ptr + (jmax - 1)) != ZERO)
  157.       border_err (ir + 1, jmax - 1);
  158.  
  159.     char_ptr = *(window + ((ir + 2) % WINDOW_ROWS));
  160.     for (jc = 0; jc < jmax; jc++)
  161.       if (*(char_ptr + jc) != ZERO)
  162.         border_err (ir + 2, jc);
  163.   }
  164.   else {
  165.     char_ptr = *(window + (ir % WINDOW_ROWS));
  166.     if (*(char_ptr) != ZERO)
  167.       border_err (ir, 0);
  168.     if (*(char_ptr + (jmax - 1)) != ZERO)
  169.       border_err (ir, jmax - 1);
  170.   }
  171. }
  172.  
  173. /*
  174.  * memory allocation for image (one row at a time)
  175.  */
  176. int
  177. img_alloc (unsigned char *img[], int nr, int nc)
  178. {
  179.   int ir;
  180.  
  181.   for (ir = 0; ir < nr; ir++) {
  182.     if ((*(img + ir) = (unsigned char *) calloc (nc, sizeof (unsigned char))) == NULL)
  183.         return (0);
  184.     else
  185.       *(img + ir) += 0;
  186.  
  187.   }
  188.   return (1);
  189. }
  190.  
  191.  
  192. void
  193. main (int argc, char *argv[])
  194. {
  195.   unsigned char *window[WINDOW_ROWS];
  196.   int ir;
  197.   int nr, nc;
  198.   int jmin, imin, jmax, imax;
  199.   int left_x, right_x;
  200.   float *delta_phikp, *delta_lkp;
  201.   Image *imgIn;                 /* input image */
  202.   Image *imgOut;                /* output image */
  203.   int i_arg;
  204.  
  205. /*
  206.  * cmd line options
  207.  */
  208.   static char *optstring = "c:bL";
  209.  
  210.  
  211. /*
  212.  * parse command line
  213.  */
  214.   optind = 3;                   /* set getopt to point to the 3rd arg */
  215.   opterr = ON;                  /* give error messages */
  216.  
  217.  
  218.   if (argc < 3)
  219.     usage (argv[0]);
  220.  
  221.   while ((i_arg = getopt (argc, argv, optstring)) != EOF) {
  222.     switch (i_arg) {
  223.     case 'L':
  224.       print_sos_lic ();
  225.       exit (0);
  226.     default:
  227.       printf ("\ngetopt: unknown condition encountered\n");
  228.       exit (1);
  229.       break;
  230.     }
  231.   }
  232.  
  233. /*
  234.  * initialize structures
  235.  */
  236.   init_structs ();
  237.  
  238. /*
  239.  * get the input image
  240.  */
  241.   imgIn = ImageIn (argv[1]);
  242.   if (imgIn->bps == 8 && imgIn->spp == 3) {
  243.     printf ("Got RGB image!!!\n");
  244.     fprintf (stderr, "Can only work with Grayscale or Binary TIFF files!!!\n");
  245.     exit (1);
  246.   }
  247.  
  248.   /* reset tiffInput so that we write a grayscale file (i.e tags are not copied) */
  249.   tiffInput = 0;
  250. /*
  251.  * initialize for output image (Grayscale!!)
  252.  */
  253.   imgOut = ImageAlloc (imgIn->height, imgIn->width, 8);
  254.  
  255.   jmin = imin = 0;
  256.   jmax = imgIn->width;
  257.   imax = imgIn->height;
  258.  
  259.   left_x = jmin;
  260.   right_x = jmax - 1;
  261.   nc = jmax - jmin;
  262.   nr = imax - imin;
  263.  
  264. #ifdef DEBUG
  265.   printf ("\n...nc = %d, nr = %d\n", nc, nr);
  266. #endif
  267.  
  268. /*
  269.  *  zero outer border of image
  270.  */
  271.   zero_border (imgIn, 2);
  272.  
  273. /*
  274.  * allocate memory
  275.  */
  276.   if ((img_alloc (window, WINDOW_ROWS, nc) == 0))
  277.     exitmess ("window", 1);
  278.  
  279.   printf ("\n...scan image...\n");
  280.   xfer_first_3_rows (window, imgIn);
  281.   for (ir = 0; ir < imax - WINDOW_ROWS; ir++) {
  282.     check_border (window, ir, jmax, imax, imgIn);
  283.     curvature_points (window, ir, jmax, imax);
  284.     xfer_next_row (window, ir, imgIn);
  285.   }
  286.   check_border (window, ir, jmax, imax, imgIn);
  287.   curvature_points (window, ir, jmax, imax);
  288.  
  289.  
  290.   if ((delta_phikp = (float *) calloc (ncp, sizeof (float))) == NULL)
  291.       exitmess ("delta_phik", 1);
  292.   if ((delta_lkp = (float *) calloc (ncp, sizeof (float))) == NULL)
  293.       exitmess ("delta_phik", 1);
  294.   delta_phik = delta_phikp;
  295.   delta_lk = delta_lkp;
  296.  
  297. /*
  298.  * construct lists representing individual boundaries
  299.  */
  300.   printf ("...construct linked lists of boundary points...\n");
  301.   linkage (imgIn, imgOut, WHITE);
  302.  
  303.  
  304.  
  305.   free (delta_phikp);
  306.   free (delta_lkp);
  307.   printf ("\n...writing graphics output file %s\n", argv[2]);
  308.   ImageOut (argv[2], imgOut);
  309. }
  310.